package com.cvte.vdt.btcontrolui.view.widget;

/**
 * Created by user on 2019/1/9.
 */

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

import com.cvte.vdt.btcontrolui.R;
import com.cvte.vdt.btcontrolui.util.LogUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Created by yamasakitaishi on 2017/05/25.
 *
 * @author Taishi Yamasaki ( https://github.com/Taishi-Y )
 */

public class Indicator extends View {
    private final String TAG = "Indicator";
    private final static int MSG_UPDATE_INDICATOR = 0;

    private Paint paint;
    private int stepNum = 10;

    private int duration = 3000;
    private int barNum = 3;
    private int barColor = 0xff000000;
    private boolean isAnim = false;

    private int viewHeight;
    private int viewWidth;

    private Status status;

    private List<ValueAnimator> runList;
    private List<ValueAnimator> endList;
    private List<ValueAnimator> startList;



    public Indicator(Context context) {
        super(context);
    }

    public Indicator(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.Indicator, 0, 0);
        try {
            isAnim = ta.getBoolean(R.styleable.Indicator_anim,false);
            barNum = ta.getInt(R.styleable.Indicator_bar_num, 3);
            stepNum = ta.getInt(R.styleable.Indicator_step_num, 10);
            duration = ta.getInt(R.styleable.Indicator_duration, 3000);
            barColor = ta.getColor(R.styleable.Indicator_bar_color, 0xff000000);
            status = Status.STOP;
            List<Float> floatList = getGraduateFloatList(stepNum);
            generateAnim(floatList, barNum);
        } finally {
            ta.recycle();
        }
    }

    public Indicator(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        paint = new Paint();
        paint.setColor(barColor);

        drawIndicator(canvas, barNum);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        viewWidth = MeasureSpec.getSize(widthMeasureSpec);
        viewHeight = MeasureSpec.getSize(heightMeasureSpec);
        this.setMeasuredDimension(viewWidth, viewHeight);

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    // 1割ずつの数列を作る
    private List<Float> getGraduateFloatList(int arraySize) {
        List<Float> floatList = new ArrayList();
        double dividedMax = 1.0 / arraySize;

        for(int i=1; i <= arraySize; i++){
            double a = i * dividedMax;
            floatList.add((float) a);
        }
        floatList.set(floatList.size()-1, floatList.get(0));

        return floatList;
    }

    private void generateAnim(List<Float> floatList, int barNum) {
        runList = new ArrayList<>();
        endList = new ArrayList<>();
        startList = new ArrayList<>();

        for (int i = 0; i < barNum; i++) {

            ValueAnimator endAnim = new ValueAnimator();
            endAnim.setFloatValues(0,1);
            endAnim.setDuration(300);
            endAnim.setRepeatCount(0);
            endAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    invalidate();
                }
            });
            endAnim.start();
            endList.add(endAnim);


            Collections.shuffle(floatList);
            floatList.set(floatList.size() - 1, floatList.get(0));

            float[] floatArray = new float[floatList.size()];
            int j = 0;
            for (Float f : floatList) {
                floatArray[j++] = (f != null ? f : Float.NaN);
            }

            ValueAnimator run = new ValueAnimator();
            run .setFloatValues(floatArray);
            run.setDuration(duration);
            run.setRepeatCount(ValueAnimator.INFINITE);
            run.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    invalidate();
                }
            });
            run.start();
            run.pause();
            runList.add(run);

            ValueAnimator startAnim = new ValueAnimator();
            startAnim.setFloatValues(1,0);
            startAnim.setDuration(300);
            startAnim.setRepeatCount(0);
            startAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    invalidate();
                }
            });
            startAnim.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {

                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    if(status != Status.RUN) {
                        status = Status.RUN;
                        for (ValueAnimator valueAnimator:runList) {
                            valueAnimator.resume();
                        }
                    }
                }

                @Override
                public void onAnimationCancel(Animator animation) {

                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });
            startList.add(startAnim);

        }
    }


    private void drawIndicator(Canvas canvas, int barNum) {
        // 一本あたりのすきま
        double spaceWidth = canvas.getWidth() * 0.2 / (barNum-1);
        // 一本のふとさ
        double barWidth = canvas.getWidth() * 0.8 / barNum;

        double sumWidth = spaceWidth + barWidth;

        for (int i=0; i<barNum - 1; i++) {
            float height = viewHeight;
            switch (status) {
                case RUN:
                    height = (float) (runList.get(i).getAnimatedValue()) * viewHeight;
                    break;
                case STRAT:
                    height = (float) (startList.get(i).getAnimatedValue()) * viewHeight;
                    break;
                case STOP:
                    height = (float) (endList.get(i).getAnimatedValue()) * viewHeight;
                    break;
            }
            canvas.drawRect(
                    (float) (i*sumWidth), // left
                    canvas.getHeight() - height,//height, // top
                    (float) (i*sumWidth + barWidth), // right
                    canvas.getHeight(), // bottom
                    paint // Paint
            );

            if (i == barNum - 2) {
                float heightLast = viewHeight;
                switch (status) {
                    case RUN:
                        heightLast = (float) (runList.get(i + 1).getAnimatedValue()) * viewHeight;
                        break;
                    case STRAT:
                        heightLast = (float) (startList.get(i + 1).getAnimatedValue()) * viewHeight;
                        break;
                    case STOP:
                        heightLast = (float) (endList.get(i + 1).getAnimatedValue()) * viewHeight;
                        break;
                }
                canvas.drawRect(
                        (float) ((i+1)*sumWidth), // left
                        canvas.getHeight() - heightLast,//height, // top
                        (float) ((i+1)*sumWidth + barWidth), // right
                        canvas.getHeight(), // bottom
                        paint // Paint
                );
            }
        }
    }

    public void setStepNum(int stepNum) {
        this.stepNum = stepNum;
    }

    public void setDuration(int duration) {
        this.duration = duration;
    }

    public void setBarNum(int barNum) {
        this.barNum = barNum;
    }

    public void setBarColor(int barColor) {
        this.barColor = barColor;
    }

    public void startAnim(){
        if(status == Status.STOP) {
            status = Status.STRAT;
            for (int i = 0; i < barNum; i++) {
                startList.get(i).cancel();
                startList.get(i).setFloatValues(1, (float) runList.get(i).getAnimatedValue());
                startList.get(i).start();
            }
        }
    }

    public void stopAnim(){
        if(status != Status.STOP) {
            status = Status.STOP;
            for (int i = 0; i < barNum; i++) {
                runList.get(i).pause();
                endList.get(i).cancel();
                endList.get(i).setFloatValues((float) runList.get(i).getAnimatedValue(), 1);
                endList.get(i).start();
            }
        }
    }
    enum Status{
        STOP,
        RUN,
        STRAT;
    }
}

